home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-15 | 20.4 KB | 822 lines | [TEXT/CWIE] |
- #include "WindowManager.h"
- #include "Toolbox.h"
- #include "ToolboxEvent.h"
- #include "Exceptions.h"
- #include "EventLoop.h"
-
- #include <LowMem.h>
- #include <Gestalt.h>
- #include <TextUtils.h>
-
-
- DefineClass2Base(WindowManager, TModule, EventFilter);
-
-
- static void HiliteShowHideFloatingWindows(bool hiliting,bool hiding);
- static void FindScreenRectWithLargestPartOfWindow(WindowRef aWindow,Rect *theBestScreenRect, GDHandle * theBestDevice);
- static pascal void CalculateWindowAreaOnDevice(short depth,short deviceFlags,GDHandle targetDevice,long userData);
-
- #pragma segment Main
- //--------------------------------------------------------------------------------
- WindowManager::WindowManager()
- {
- fScratchRgn = nil;
- }
-
- #pragma segment AppCleanup
- //--------------------------------------------------------------------------------
- WindowManager::~WindowManager()
- {
- }
-
- #pragma segment AppInit
- //--------------------------------------------------------------------------------
- bool WindowManager::Validate(void)
- {
- fHasColorQuickdraw = Toolbox::HasGestalt(gestaltQuickdrawFeatures, gestaltHasColor);
- fHasDisplayManager = Toolbox::HasGestalt(gestaltDisplayMgrAttr, gestaltDisplayMgrPresent);
-
- return true;
- }
-
- #pragma segment AppInit
- //--------------------------------------------------------------------------------
- void WindowManager::Initialize(void)
- {
- if (!fScratchRgn)
- {
- InitializeAfter(Toolbox::GetToolbox());
-
- TModule::Initialize();
- EventFilter::Initialize();
-
- FailNIL(fScratchRgn = NewRgn());
-
- EventLoop::PushEventFilter(*this);
- }
- }
-
- //--------------------------------------------------------------------------------
-
- void WindowManager::Finalize(void)
- {
- TModule::Finalize();
- EventFilter::Finalize();
- }
-
- #pragma segment AppMain
- //--------------------------------------------------------------------------------
- bool WindowManager::Initialized(void)
- {
- return fScratchRgn != nil;
- }
-
-
- #pragma segment AppInit
- //--------------------------------------------------------------------------------
- bool WindowManager::InitializeCalled(void)
- {
- return fScratchRgn != nil;
- }
-
- //--------------------------------------------------------------------------------
-
- bool WindowManager::FilterEvent(ToolboxEvent& evt)
- {
- EventKind what = evt.GetEventKind();
- short part = inNoWindow;
- WindowRef wind = nil;
-
- switch (what)
- {
- case mouseDown:
- case mouseUp:
- part = evt.GetPartCode();
-
- switch (part)
- {
- case inDrag:
- DragWindow(wind, evt.GetMousePosition());
- return true;
-
- case inGrow:
- GrowWindow(wind, evt.GetMousePosition());
- return true;
-
- case inGoAway:
- CloseWindow(wind);
- return true;
-
- case inZoomIn:
- case inZoomOut:
- ZoomWindow(wind, part);
- return true;
-
- default:
- return false;
- }
- break;
-
- /* MacWindows.h
-
- case keyDown:
- case keyUp:
- case autoKey:
- wind = FrontWindow(kNormalWindowLayer);
- goto window_event;
- */
-
-
- /*
-
- case updateEvt:
- UpdateWindow((WindowRef) msg);
- break;
-
- case activateEvt:
- if (evt.modifiers & activeFlag)
- {
- ActivateWindow(evt.GetWindow());
- }
- else
- {
- DeactivateWindow(evt.GetWindow());
- }
- break;
-
- case osEvt:
- if (((msg & osEvtMessageMask) >> 24) == suspendResumeMessage)
- {
- if (msg & suspendResumeMessage)
- {
- ResumeApplication();
- }
- else
- {
- SuspendApplication();
- }
- }
- default:
- return false;
- */
- }
-
- return true;
- }
-
- //------------------------------------------------------------------------------
-
- WindowRef WindowManager::NewWindow(
- const Rect& boundsRect,
- ConstStr255Param title,
- bool visible,
- short theProc,
- WindowRef behind,
- bool goAwayFlag,
- long refCon,
- WindowLayer /*layer*/)
- {
- WindowRef win;
-
- if (fHasColorQuickdraw)
- win = ::NewCWindow(nil,&boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
- else
- win = ::NewWindow(nil,&boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
-
- FailNIL(win);
-
- return win;
- }
-
-
- WindowRef WindowManager::GetNewWindow(
- short windowID,
- WindowRef behind,
- WindowLayer /*layer*/)
- {
- WindowRef win;
-
- // get the window from the resource file
- if (fHasColorQuickdraw)
- win = ::GetNewCWindow(windowID, nil, behind);
- else
- win = ::GetNewWindow(windowID, nil, behind);
-
- FailNIL(win);
-
- return win;
- }
-
-
- void WindowManager::DisposeWindow(WindowRef aWindow)
- {
- ::DisposeWindow(aWindow);
- }
-
-
- void WindowManager::SelectWindow(WindowRef aWindow)
- {
- ::SelectWindow(aWindow);
- }
-
- void WindowManager::UpdateWindow(WindowRef aWindow)
- {
- ::BeginUpdate(aWindow);
- DrawGrowIcon(aWindow);
- ::EndUpdate(aWindow);
- }
-
- void WindowManager::ActivateWindow(WindowRef aWindow)
- {
- ::HiliteWindow(aWindow, true);
- }
-
- void WindowManager::DeactivateWindow(WindowRef aWindow)
- {
- ::HiliteWindow(aWindow, false);
- }
-
- void WindowManager::ShowWindow(WindowRef aWindow)
- {
- ::ShowWindow(aWindow);
- }
-
- void WindowManager::HideWindow(WindowRef aWindow)
- {
- ::HideWindow(aWindow);
- }
-
- void WindowManager::CloseWindow(WindowRef aWindow)
- {
- ::CloseWindow(aWindow);
- }
-
- void WindowManager::SuspendApplication()
- {
- this->HiliteShowHideFloatingWindows(false, false);
- }
-
- void WindowManager::ResumeApplication()
- {
- this->HiliteShowHideFloatingWindows(true, true);
- }
-
- void WindowManager::BeginModalDialog()
- {
- this->HiliteShowHideFloatingWindows(false, false);
- }
-
- void WindowManager::EndModalDialog()
- {
- this->HiliteShowHideFloatingWindows(true, false);
- }
-
- void WindowManager::HiliteShowHideFloatingWindows(bool active, bool /*hide*/)
- {
- if (active)
- this->ActivateWindow(FrontWindow(kNormalWindowLayer));
- else
- this->DeactivateWindow(FrontWindow(kNormalWindowLayer));
- }
-
- WindowLayer WindowManager::GetWindowLayer(WindowRef /*aWindow*/)
- {
- return kNormalWindowLayer;
- }
-
- WindowRef WindowManager::FrontWindow(WindowLayer layer)
- {
- switch (layer)
- {
- case kAnyWindowLayer:
- case kNormalWindowLayer:
- return ::FrontWindow();
-
- default:
- Debugger();
- }
-
- return nil;
- }
-
- WindowRef WindowManager::BackWindow(WindowLayer layer)
- {
- switch (layer)
- {
- case kAnyWindowLayer:
- case kNormalWindowLayer:
- {
- WindowRef win;
-
- for (win = ::FrontWindow(); ::GetNextWindow(win); win = ::GetNextWindow(win)) {}
-
- return win;
- }
- break;
-
- default:
- Debugger();
- }
-
- return nil;
- }
-
- //--------------------------------------------------------------------------------
- WindowRef WindowManager::GetNthWindow(long index, WindowLayer layer)
- {
- WindowRef win = FrontWindow(kNormalWindowLayer);
-
- if (index > 0)
- {
- while (win != nil && --index >= 0)
- {
- if (index == 0)
- {
- return win;
- }
-
- win = GetNextWindow(win);
- }
- }
- else
- {
- DebugStr("\pWe don't do negatives yet");
- }
-
-
- return nil;
- }
-
-
- //--------------------------------------------------------------------------------
- // find any type of window with the input name
- WindowRef WindowManager::GetNamedWindow(ConstStr255Param winName, WindowLayer layer)
- {
- Str255 thisName;
-
- WindowRef win = FrontWindow(kNormalWindowLayer);
-
- while (win != nil)
- {
- GetWTitle(win, thisName);
-
- // compare the titles
- if (EqualString(winName, thisName, false, true))
- return win;
-
- win = GetNextWindow(win);
- }
-
- return nil;
- }
-
-
- //--------------------------------------------------------------------------------
- /// Not done yet!!! - ONLY deals with non-floating windows
- long WindowManager::GetWindowIndex(WindowRef aWindow, WindowLayer layer)
- {
- WindowRef win = this->FrontWindow(kNormalWindowLayer);
- long index = 0;
-
- // look for ourself among the non-floating windows
- while (win != nil)
- {
- index++;
- if (win == aWindow)
- return index;
-
- win = ::GetNextWindow(win);
- }
-
- return index;
- }
-
-
-
- bool WindowManager::IsWindowVisible(WindowRef aWindow)
- {
- return ::IsWindowVisible(aWindow);
- }
-
- bool WindowManager::IsWindowHilited(WindowRef aWindow)
- {
- return ::IsWindowHilited(aWindow);
- }
-
- bool WindowManager::IsWindowModal(WindowRef aWindow)
- {
- short variant = ::GetWVariant(aWindow);
- SInt16 kind = ::GetWindowKind(aWindow);
-
- return variant == kModalDialogVariantCode
- || variant == kMovableModalDialogVariantCode;
- }
-
- bool WindowManager::IsWindowFloating(WindowRef aWindow)
- {
- return false;
- }
-
- bool WindowManager::IsDialogWindow(WindowRef aWindow)
- {
- return false;
- }
-
- //--------------------------------------------------------------------------------
- bool WindowManager::PointInStructureRgn(WindowRef aWindow, Point pt)
- {
- GetWindowContentRgn(aWindow, fScratchRgn);
- bool result = PtInRgn( pt, fScratchRgn );
- return result;
- }
-
- //--------------------------------------------------------------------------------
- bool WindowManager::PointInContentRgn(WindowRef aWindow, Point pt)
- {
- GetWindowContentRgn(aWindow, fScratchRgn);
- bool result = PtInRgn( pt, fScratchRgn );
- return result;
- }
-
- //--------------------------------------------------------------------------------
- Rect WindowManager::GetWindowStructureBounds(WindowRef aWindow)
- {
- GetWindowContentRgn(aWindow, fScratchRgn);
- return (**fScratchRgn).rgnBBox;
- }
-
- //--------------------------------------------------------------------------------
- Rect WindowManager::GetWindowContentBounds(WindowRef aWindow)
- {
- GetWindowContentRgn(aWindow, fScratchRgn);
- return (**fScratchRgn).rgnBBox;
- }
-
- //--------------------------------------------------------------------------------
- void WindowManager::SetWindowBounds(WindowRef aWindow, Rect newBounds)
- {
- ::MoveWindow( aWindow, newBounds.left, newBounds.top, false);
- ::SizeWindow( aWindow, newBounds.right-newBounds.left, newBounds.bottom-newBounds.top, true );
- }
-
-
- //--------------------------------------------------------------------------------
- void WindowManager::DragWindow(WindowRef aWindow, Point startPoint)
- {
- KeyMap theKeyMap;
- bool commandKeyDown = false;
- long dragResult;
-
- if (WaitMouseUp()) // de-bounce?
- {
- {
- WithWindowManagerPort wmPort;
-
- // Set up the Window Manager port.
-
- SetClip(GetGrayRgn());
-
- // Check to see if the command key is down.
-
- GetKeys(theKeyMap);
- commandKeyDown = ((theKeyMap[1] & 0x8000) != 0);
-
- if (commandKeyDown)
- {
- // We’re not going to change window ordering,
- // so make sure that we don’t drag in front of
- // other windows which may be in front of ours.
-
- ClipAbove(aWindow);
- }
- else if (IsWindowFloating(aWindow))
- {
- // We’re dragging a normal window, so make sure
- // that we don’t drag in front of any floating
- // windows.
-
- ClipAbove(FrontWindow(kNormalWindowLayer));
- }
-
- // Drag an outline of the window around the desktop.
- // NOTE: DragGrayRgn destroys the region passed in, so make a copy
-
- RgnHandle grayRgn = GetGrayRgn();
- Rect deskRect = (**grayRgn).rgnBBox;
-
- GetWindowStructureRgn(aWindow, fScratchRgn);
- dragResult = DragGrayRgn(fScratchRgn, startPoint, &deskRect, &deskRect, noConstraint, nil);
- }
-
- if ((dragResult != 0) && (dragResult != 0x80008000))
- {
- WindowManager::NudgeWindow(aWindow, (short) (dragResult & 0xFFFF),(short) (dragResult >> 16));
- }
- }
-
- if (!commandKeyDown)
- WindowManager::SelectWindow(aWindow);
- }
-
-
- //--------------------------------------------------------------------------------
- void WindowManager::NudgeWindow(WindowRef aWindow, short horizontalDistance, short verticalDistance)
- {
- short newHorizontalPosition,newVerticalPosition;
- RgnHandle tempRgn = NewRgn ();
-
- GetWindowContentRgn ( aWindow, tempRgn );
- newHorizontalPosition = (short) (**tempRgn).rgnBBox.left + horizontalDistance;
- newVerticalPosition = (short) (**tempRgn).rgnBBox.top + verticalDistance;
- DisposeRgn ( tempRgn );
-
- ::MoveWindow(aWindow,newHorizontalPosition,newVerticalPosition,false);
- }
-
-
- //--------------------------------------------------------------------------------
- void WindowManager::GrowWindow(WindowRef aWindow, Point startPoint, const Rect* resizeLimits)
- {
- GrafPtr oldPort;
- long newSize;
- Rect oldWindowRect;
-
- const Rect limits = {0, 0, 32000, 32000};
-
- if (resizeLimits = nil)
- {
- resizeLimits = &limits;
- }
-
- GetPort(&oldPort);
-
- newSize = ::GrowWindow(aWindow, startPoint, resizeLimits);
- if (newSize)
- {
- oldWindowRect = GetWindowPort ( aWindow )->portRect;
- ::SizeWindow ( aWindow, (short) newSize, (short) (newSize >> 16), true );
- SetPortWindowPort ( aWindow );
- // resizeLimits = GetWindowPort ( aWindow )->portRect;
- // this->AdjustForNewWindowSize(&oldWindowRect,&resizeLimits);
- }
- SetPort(oldPort);
- }
-
-
-
- //--------------------------------------------------------------------------------
- void WindowManager::ZoomWindow(WindowRef aWindow, short zoomState, const Rect* perfectWindowRect)
- {
- FontInfo systemFontInfo;
- short titleBarHeight;
- Rect bestScreenRect,scratchRect;
- short amountOffscreen;
- GDHandle bestDevice;
-
- // Figure out the height of the title bar so we can properly position
- // a window. The algorithm is stolen from the System 7.x 'WDEF' (0)
- //
- // This probably isn’t the best thing to do: A better way might be
- // to diff the structure and content region rectangles?
-
- WithWindowManagerPort wmPort;
-
- GetFontInfo(&systemFontInfo);
- titleBarHeight = (short) (systemFontInfo.ascent + systemFontInfo.descent + 4);
- if ((titleBarHeight % 2) == 1)
- titleBarHeight--;
- if (titleBarHeight < kMinimumTitleBarHeight)
- titleBarHeight = kMinimumTitleBarHeight;
-
- // Only do the voodoo magic if we are really “zooming” the window.
-
- #if 0
-
- if (zoomState == inZoomOut)
- {
- FindScreenRectWithLargestPartOfWindow(aWindow,&bestScreenRect,&bestDevice);
- bestScreenRect.top += titleBarHeight;
-
- // this->GetPerfectWindowSize(&perfectWindowRect);
- OffsetRect(&perfectWindowRect,-perfectWindowRect.left,-perfectWindowRect.top);
-
- // Take the zero-pined perfect window size and move it to
- // the top left of the window’s content region.
-
- RgnHandle tempRgn = NewRgn ();
- GetWindowContentRgn ( aWindow, tempRgn );
- OffsetRect ( &perfectWindowRect,
- (**tempRgn).rgnBBox.left, (**tempRgn).rgnBBox.top );
- DisposeRgn ( tempRgn );
-
- // Does perfectWindowRect fit completely on the best screen?
-
- SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
- if (!EqualRect(&perfectWindowRect, &scratchRect))
- {
- // SectRect sez perfectWindowRect doesn’t completely fit
- // on the screen, so bump the window so that more of it fits.
-
- // Make sure that the left edge of perfectWindowRect is forced
- // onto the best screen. This is in case we are bumping
- // the window to the right.
-
- amountOffscreen = bestScreenRect.left - perfectWindowRect.left;
- if (amountOffscreen > 0)
- {
- perfectWindowRect.left += amountOffscreen;
- perfectWindowRect.right += amountOffscreen;
- }
-
- // Make sure that the left edge of perfectWindowRect is forced
- // onto the best screen. This is in case we are bumping
- // the window downward to a new screen.
-
- amountOffscreen = bestScreenRect.top - perfectWindowRect.top;
- if (amountOffscreen > 0)
- {
- perfectWindowRect.top += amountOffscreen;
- perfectWindowRect.bottom += amountOffscreen;
- }
-
- // If right edge of window falls off the screen,
- // Move window to the left until the right edge IS on the screen
- // OR the left edge is at bestScreenRect.left
-
- amountOffscreen = perfectWindowRect.right - bestScreenRect.right;
- if (amountOffscreen > 0)
- {
- // Are we going to push the left edge offscreen? If so, change the
- // offset so we move the window all the way over to the left.
-
- if ((perfectWindowRect.left - amountOffscreen) < bestScreenRect.left)
- amountOffscreen = perfectWindowRect.left - bestScreenRect.left;
-
- perfectWindowRect.left -= amountOffscreen;
- perfectWindowRect.right -= amountOffscreen;
- }
-
- // If bottom edge of window falls off the screen,
- // Move window to up until the bottom edge IS on the screen
- // OR the top edge is at bestScreenRect.top
-
- amountOffscreen = perfectWindowRect.bottom - bestScreenRect.bottom;
- if (amountOffscreen > 0)
- {
- // Are we going to push the top edge offscreen? If so, change the
- // offset so we move the window just to the top.
-
- if ((perfectWindowRect.top - amountOffscreen) < bestScreenRect.top)
- amountOffscreen = perfectWindowRect.top - bestScreenRect.top;
-
- perfectWindowRect.top -= amountOffscreen;
- perfectWindowRect.bottom -= amountOffscreen;
- }
-
- SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
- if (!EqualRect(&perfectWindowRect, &scratchRect))
- {
- // The edges of the window still fall offscreen,
- // so make the window smaller until it fits.
-
- if (perfectWindowRect.bottom > bestScreenRect.bottom)
- perfectWindowRect.bottom = bestScreenRect.bottom;
-
- // If the right edge is still falling off,
- // save space for Finder’s disk icons as well.
-
- if (perfectWindowRect.right > bestScreenRect.right)
- {
- perfectWindowRect.right = bestScreenRect.right;
-
- // If we were on the main screen, leave room for Finder icons, too.
-
- if (bestDevice == GetMainDevice())
- perfectWindowRect.right -= kSpaceForFinderIcons;
- }
- }
- }
-
- // Stash our new rectangle inside of the Window’s dataHandle
- // so that ZoomWindow does the right thing.
-
- SetWindowStandardState ( aWindow, &perfectWindowRect );
- }
-
- #endif
-
- // HEY YOU! Don’t forget to set the port to the window being zoomed
- // Why, you ask? Because IM-IV-50 says to; otherwise you die
-
- WithWindowPort winPort(aWindow);
-
- Rect oldWindowRect = GetWindowPort ( aWindow )->portRect;
- ::ZoomWindow(aWindow,zoomState,false);
- Rect newWindowRect = GetWindowPort ( aWindow )->portRect;
-
- // this->AdjustForNewWindowSize(&oldWindowRect,&newWindowRect);
- }
-
- //--------------------------------------------------------------------------------
-
-
- void WindowManager::DrawWindowGrowIcon(WindowRef aWindow)
- {
- GrafPtr savedPort;
- Rect growBoxRect;
-
- GetPort(&savedPort);
- SetPortWindowPort ( aWindow );
- GetClip(fScratchRgn);
-
- // clip to just the bottom right corner of the window
- growBoxRect = GetWindowPort ( aWindow )->portRect;
- growBoxRect.top = growBoxRect.bottom - kScrollbarWidth;
- growBoxRect.left = growBoxRect.right - kScrollbarWidth;
- ClipRect(&growBoxRect);
-
- DrawGrowIcon(aWindow);
-
- SetClip(fScratchRgn);
- SetPort(savedPort);
- }
-
-
- //--------------------------------------------------------------------------------
- // Routines used for dealing with windows and multiple screens
- //--------------------------------------------------------------------------------
-
- struct CalcWindowAreaDeviceLoopUserData
- {
- GDHandle fScreenWithLargestPartOfWindow;
- long fLargestArea;
- Rect fWindowBounds;
- };
-
-
- //--------------------------------------------------------------------------------
- pascal void CalculateWindowAreaOnDevice(short /* depth */, short /* deviceFlags */,
- GDHandle targetDevice,long userData)
- {
- CalcWindowAreaDeviceLoopUserData * deviceLoopDataPtr;
- long windowAreaOnThisScreen;
- Rect windowRectOnThisScreen;
-
- deviceLoopDataPtr = (CalcWindowAreaDeviceLoopUserData *) userData;
-
- SectRect(&deviceLoopDataPtr->fWindowBounds, &(**targetDevice).gdRect,&windowRectOnThisScreen);
- OffsetRect(&windowRectOnThisScreen,-windowRectOnThisScreen.left,-windowRectOnThisScreen.top);
- windowAreaOnThisScreen = windowRectOnThisScreen.right * windowRectOnThisScreen.bottom;
-
- if (windowAreaOnThisScreen > deviceLoopDataPtr->fLargestArea)
- {
- deviceLoopDataPtr->fLargestArea = windowAreaOnThisScreen;
- deviceLoopDataPtr->fScreenWithLargestPartOfWindow = targetDevice;
- }
- }
-
-
- DeviceLoopDrawingUPP CallCalcWindowAreaOnDevice = NewDeviceLoopDrawingProc(&CalculateWindowAreaOnDevice);
-
-
- //--------------------------------------------------------------------------------
- void FindScreenRectWithLargestPartOfWindow( WindowRef aWindow,Rect *theBestScreenRect,
- GDHandle * theBestDevice)
- {
- RgnHandle copyOfWindowStrucRgn;
- CalcWindowAreaDeviceLoopUserData deviceLoopData;
-
- // Use DeviceLoop to find out what GDevice contains the largest
- // portion of the supplied window.
- //
- // NOTE: Assumes thePort == the Window Manager Port because we using
- // the window strucRgn, not contRgn.
-
- deviceLoopData.fScreenWithLargestPartOfWindow = nil;
- deviceLoopData.fLargestArea = -1;
-
- RgnHandle tempRgn = NewRgn ();
- GetWindowContentRgn ( aWindow, tempRgn );
- deviceLoopData.fWindowBounds = (**tempRgn).rgnBBox;
- DisposeRgn ( tempRgn );
-
- copyOfWindowStrucRgn = NewRgn();
- GetWindowStructureRgn ( aWindow, copyOfWindowStrucRgn );
-
- DeviceLoop(copyOfWindowStrucRgn,CallCalcWindowAreaOnDevice,(long) &deviceLoopData,singleDevices);
-
- DisposeRgn(copyOfWindowStrucRgn);
-
- *theBestDevice = deviceLoopData.fScreenWithLargestPartOfWindow;
- *theBestScreenRect = (**(deviceLoopData.fScreenWithLargestPartOfWindow)).gdRect;
-
- // Leave some space around the edges of the screen so window look good, AND
- // if the best device is the main screen, leave space for the Menubar
-
- InsetRect(theBestScreenRect,kScreenEdgeSlop,kScreenEdgeSlop);
- if (GetMainDevice() == deviceLoopData.fScreenWithLargestPartOfWindow)
- theBestScreenRect->top += GetMBarHeight();
- }
-
-
-